package thread;

/**
 * 将多线程并发执行临界资源改为同步执行可有效解决并发安全问题。
 * 使用同步块可以更准确的锁定需要同步执行的代码片段，当有效的缩小同步范围可以在保证
 * 并发安全的前提下尽可能提高并发效率
 *
 * 同步与异步执行都是指线程之间的执行方式
 * 同步执行:线程之间执行存在先后顺序
 * 异步执行:线程之间各干各的，互补干扰
 *
 * 语法:
 * synchronized(同步监视器对象){
 *     需要同步执行的代码片段
 * }
 */
public class SyncDemo2 {
    public static void main(String[] args) {
//        Shop shop = new Shop();
        Shop s1 = new Shop();
        Shop s2 = new Shop();
        Thread fan = new Thread("范传奇"){
            public void run(){
//                shop.buy();
                s1.buy();
            }
        };
        Thread wang = new Thread("王克晶"){
            public void run(){
//                shop.buy();
                s2.buy();
            }
        };
        fan.start();
        wang.start();
    }
}

class Shop{
    /*
        在成员方法上如果使用synchronized，那么该方法称为同步方法。
        此时同步监视器对象不可选，只能是this。
     */
//    public synchronized void buy(){
    public void buy(){
        try {
            Thread t = Thread.currentThread();//获取执行该方法的线程
            System.out.println(t.getName()+":正在挑衣服...");
            Thread.sleep(5000);
            /*
                同步监视器对象的选取原则
                1:必须是一个引用类型对象
                2:同个线程看到的必须是同一个对象
                3:该同步时能限制多个线程同步(同一个同步监视器对象)，
                  不该同步时可以并发执行(不是同一个同步见其对象)。

                通常指定的同步监视器对象为临界资源对象(抢谁就锁谁)
             */
            synchronized (this) {
//            synchronized (new Object()) {//使用new一定无效
                System.out.println(t.getName() + ":正在试衣服...");
                Thread.sleep(5000);
            }
            System.out.println(t.getName()+":结账离开");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}




